//
// Convention2JavaParams
//
// Copyright (C) jextra.net.
//
//  This file is part of the Crack build system.
//
//  The Crack build system is free software; you can redistribute it 
//  and/or modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2.1 of the License, or (at your option) any later version.
//
//  The Crack build system is distributed in the hope that it will be 
//  useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with the Crack build system; if not, write to the Free
//  Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
//  02111-1307 USA.
//

package net.jextra.crack.java;

import java.io.*;
import java.util.*;
import net.jextra.crack.*;
import net.jextra.crack.props.*;
import net.jextra.crack.tool.*;
import net.jextra.crack.type.*;

/**
 * <p>
 * A "standard" convention of directories for development of Java code. This is more "maven"-like with the baroque
 * src/main/java and src/test/java source paths.
 * </p>
 * <p>
 * These parameters assume a standard directory structure of:
 * </p>
 * 
 * <pre>
 * PROJECT_ROOT_DIR/
 *     env - Environment directory for location of environment.properties file (overrides).
 *     COMPONENT_ROOT_DIR/
 *         src/main/java/ - Source code (and location of Build.crack file).
 *         version.properties
 *     target/
 *         classes/ - Compiled classes.
 *         docs/apidocs/ - JavaDoc.
 *         build/ - Directory of packaged jar files.
 *         shrinkwrap/ - Directory of staging area for deployment.
 * </pre>
 */
public class Convention2JavaParams
{
    // ============================================================
    // Fields
    // ============================================================

    public static final String DIR_ROOT = "..";
    public static final String DIR_MAIN_SOURCE = "src/main/java";
    public static final String DIR_TEST_SOURCE = "src/test/java";
    public static final String DIR_JAVADOC = "../target/docs/apidocs";
    public static final String DIR_BUILD_ROOT = "../target/build";
    public static final String DIR_SHRINKWRAP = "../target/shrinkwrap";
    public static final String DIR_CLASSES = "../target/classes";

    public static final String FILE_VERSION_PROPERTIES = "version.properties";
    public static final String PROP_VERSION_NUMBER = "version.number";
    public static final String DEFAULT_VERSION_NUMBER = "0.0.0.1";

    private String versionNumber;
    private File projectRootDir;
    private File componentRootDir;
    private ArrayList<File> sourceDirs;
    private String packagePrefix;
    private File classesDir;
    private File javadocDir;
    private File envDir;
    private File buildDir;
    private File shrinkwrapDir;
    private FileStrainer javaSourceStrainer;
    private FileStrainer resourceStrainer;

    // ============================================================
    // Constructors
    // ============================================================

    public Convention2JavaParams()
    {
        try
        {
            RootFinder rootFinder = new RootFinder();
            componentRootDir = rootFinder.getRoot( CrackBuild.getInstance(), DIR_MAIN_SOURCE );
            projectRootDir = componentRootDir.getParentFile();
            packagePrefix = rootFinder.getPackagePrefix( CrackBuild.getInstance() );

            // Read the version properties file at component root dir.
            Properties versionProps = new Properties();
            File versionFile = new File( componentRootDir, FILE_VERSION_PROPERTIES );
            versionNumber = DEFAULT_VERSION_NUMBER;
            if ( versionFile.exists() )
            {
                FileInputStream in = new FileInputStream( versionFile );
                versionProps.load( in );
                in.close();
                versionNumber = (String) versionProps.get( PROP_VERSION_NUMBER );
            }

            sourceDirs = new ArrayList<File>();
            sourceDirs.add( new File( componentRootDir, DIR_MAIN_SOURCE ) );
            File testDir = new File( componentRootDir, DIR_TEST_SOURCE );
            if ( testDir.exists() )
            {
                sourceDirs.add( testDir );
            }
            classesDir = new File( componentRootDir, DIR_CLASSES );
            javadocDir = new File( componentRootDir, DIR_JAVADOC );
            buildDir = new File( componentRootDir, DIR_BUILD_ROOT );
            shrinkwrapDir = new File( componentRootDir, DIR_SHRINKWRAP );

            javaSourceStrainer = new RegexFileStrainer( new SimpleDirStrainer( packagePrefix ) ).include( ".*\\.java" )
                .exclude( ".*\\.crack" );
            resourceStrainer = new RegexFileStrainer( new SimpleDirStrainer( packagePrefix ) ).exclude( ".*\\.java" )
                .exclude( ".*\\.crack" );
        }
        catch ( Exception ex )
        {
            throw new CrackException( ex );
        }
    }

    // ============================================================
    // Methods
    // ============================================================

    // ----------
    // public
    // ----------

    public File getProjectRootDir()
    {
        return projectRootDir;
    }

    public File getComponentRootDir()
    {
        return componentRootDir;
    }

    public void setRootDir( File rootDir )
    {
        componentRootDir = rootDir;
    }

    public Collection<File> getSourceDirs()
    {
        return sourceDirs;
    }

    public Collection<File> getResourceDirs()
    {
        return sourceDirs;
    }

    public String getPackagePrefix()
    {
        return packagePrefix;
    }

    public void clearSourceDirs()
    {
        sourceDirs.clear();
    }

    public void addSourceDir( File sourceDir )
    {
        sourceDirs.add( sourceDir );
    }

    public File getClassesDir()
    {
        if ( classesDir != null )
        {
            return classesDir;
        }

        //
        // Override classesDir if specified in Props by now.
        //
        if ( CrackProps.getString( "classes.dir" ) != null )
        {
            return new File( getComponentRootDir(), CrackProps.getString( "classes.dir" ) );
        }

        return new File( componentRootDir, DIR_CLASSES );
    }

    public void setClassesDir( File classesDir )
    {
        this.classesDir = classesDir;
    }

    public File getJavadocDir()
    {
        return javadocDir;
    }

    public void setJavadocDir( File javadocDir )
    {
        this.javadocDir = javadocDir;
    }

    public FileStrainer getJavaSourceStrainer()
    {
        return javaSourceStrainer;
    }

    public void setJavaSourceStrainer( FileStrainer selfStrainer )
    {
        javaSourceStrainer = selfStrainer;
    }

    public File getEnvDir()
    {
        return envDir;
    }

    public void setEnvDir( File envDir )
    {
        this.envDir = envDir;
    }

    public File getBuildDir()
    {
        return buildDir;
    }

    public void setBuildDir( File buildDir )
    {
        this.buildDir = buildDir;
    }

    public File getShrinkwrapDir()
    {
        return shrinkwrapDir;
    }

    public void setShrinkwrapDir( File shrinkwrapDir )
    {
        this.shrinkwrapDir = shrinkwrapDir;
    }

    public String getVersionNumber()
    {
        return versionNumber;
    }

    public void setVersionNumber( String versionNumber )
    {
        this.versionNumber = versionNumber;
    }

    public FileStrainer getResourceStrainer()
    {
        return resourceStrainer;
    }

    public void setResourceStrainer( FileStrainer resourceStrainer )
    {
        this.resourceStrainer = resourceStrainer;
    }
}
